package com.example.innospace.demos.config;


import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.example.innospace.demos.pojo.entity.Admin;
import com.example.innospace.demos.pojo.entity.Student;
import com.example.innospace.demos.pojo.entity.Teacher;
import com.example.innospace.demos.utils.JWTUtils;
import com.example.innospace.demos.web.mapper.AdminMapper;
import com.example.innospace.demos.web.mapper.StudentMapper;
import com.example.innospace.demos.web.mapper.TeacherMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
* 拦截器*/
@Component
public class JwtInterceptor implements HandlerInterceptor {

    @Autowired
    private StudentMapper studentMapper;
    @Autowired
    private TeacherMapper teacherMapper;
    @Autowired
    private AdminMapper adminMapper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
    {
        //令牌验证
        String token=request.getHeader("Authorization");
        // 如果方法上加入注解直接通过,避免拦截，放行单个端口
        //检查当前请求的处理方法是否添加了 AuthAccess 注解。
        //如果添加了该注解，则表示该请求不需要进行 JWT 验证，直接放行，返回 true
        if (handler instanceof HandlerMethod) {
            AuthAccess annotation = ((HandlerMethod) handler).getMethodAnnotation(AuthAccess.class);
            if (annotation != null) {
                return true;
            }
        }
        // 令牌为空检查
        if(token == null || token.trim().isEmpty()){
            response.sendError(HttpStatus.UNAUTHORIZED.value(), "未登录");
            return false;
        }
        // 解码令牌获取用户 ID
        // 获取 token 中的 user id
        String userId = null;
        try {
            if (token != null) {
                com.auth0.jwt.interfaces.DecodedJWT decodedJWT = JWT.decode(token);
                java.util.List<String> audience = decodedJWT.getAudience();
                if (audience != null && !audience.isEmpty()) {
                    userId = audience.get(0);
                }
            }
        } catch (JWTDecodeException j) {
            // 记录日志或抛出携带详细信息的异常
            throw new RuntimeException("Failed to decode JWT token: " + j.getMessage(), j);
        }
        // TODO 这部分还是可以继续设计优化的
        // 根据 token 中的 userid 查询数据库
        int flag=0;
        if(userId!=null) {
            Student student=studentMapper.findById(userId);
            if(student!=null)
                flag=1;
            Teacher teacher=teacherMapper.findById(userId);
            if(teacher!=null)
                flag=1;
            Admin admin=adminMapper.findById(userId);
            if(admin!=null)
                flag=1;
        }
        if(flag==0)
        {
            response.sendError(HttpStatus.UNAUTHORIZED.value(), "用户不存在");
            return false;
        }
        // 用户密码加签验证 token
        //使用 JWT.require(Algorithm.HMAC256(JWTUtils.SING)).build() 创建一个 JWT 验证器，使用 JWTUtils.SING 作为密钥。
        //调用 jwtVerifier.verify(token) 方法验证令牌的签名和有效性。
        //如果验证过程中出现 JWTVerificationException 异常，向客户端发送 401（未授权）错误响应，并返回 false，表示请求被拦截。
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(JWTUtils.KEY)).build();
        try {
            jwtVerifier.verify(token); // 验证 token
        } catch (JWTVerificationException e) {
            response.sendError(HttpStatus.UNAUTHORIZED.value(), "token 验证失败");
            return false;
        }
        return true;
    }
}
